﻿
namespace HSS.Xaml.UI.Controls
{
	#region Using Directives
	using System.Windows;
	using System.Windows.Controls;
	using System.Windows.Input;

	#endregion

	#region PropertyGridLabel
	/// <summary>
	/// PropertyGridLabel
	/// </summary>
	[TemplatePart(Name = PART_LabelTextBlock, Type = typeof(TextBox))]
	[TemplateVisualState(GroupName = STATES_selectionStates, Name = STATE_SelectedActiveReadOnly)]
	[TemplateVisualState(GroupName = STATES_selectionStates, Name = STATE_SelectedInactiveReadOnly)]
	[TemplateVisualState(GroupName = STATES_selectionStates, Name = STATE_UnselectedReadOnly)]
	[TemplateVisualState(GroupName = STATES_selectionStates, Name = STATE_SelectedActive)]
	[TemplateVisualState(GroupName = STATES_selectionStates, Name = STATE_SelectedInactive)]
	[TemplateVisualState(GroupName = STATES_selectionStates, Name = STATE_Unselected)]
	public sealed class PropertyGridLabelControl : Control
	{
		#region Parts
		/// <summary>
		/// LabelTextBlock
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "PART")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores")]
		public const string PART_LabelTextBlock = "LabelTextBlock";
		/// <summary>
		/// SelectionStates
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "STATES")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "selection")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores")]
		public const string STATES_selectionStates = "SelectionStates";
		/// <summary>
		/// SelectedActiveReadOnly
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "STATE")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores")]
		public const string STATE_SelectedActiveReadOnly = "SelectedActiveReadOnly";
		/// <summary>
		/// SelectedInactiveReadOnly
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "STATE")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores")]
		public const string STATE_SelectedInactiveReadOnly = "SelectedInactiveReadOnly";
		/// <summary>
		/// UnselectedReadOnly
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "STATE")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores")]
		public const string STATE_UnselectedReadOnly = "UnselectedReadOnly";
		/// <summary>
		/// SelectedActive
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "STATE")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores")]
		public const string STATE_SelectedActive = "SelectedActive";
		/// <summary>
		/// SelectedInactive
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "STATE")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores")]
		public const string STATE_SelectedInactive = "SelectedInactive";
		/// <summary>
		/// Unselected
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "STATE")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores")]
		public const string STATE_Unselected = "Unselected";
		#endregion

		#region Events
		/// <summary>
		/// Event fired when the user Double Clicks the Entry Label
		/// </summary>
		public event RoutedEventHandler DoubleClick;
		void OnDoubleClick(System.Windows.Input.MouseButtonEventArgs e)
		{
			var handler = DoubleClick;
			if (null != handler)
				handler(this, e);
		}
		#endregion

		#region Fields
		bool isReadOnly = false;
		readonly object key = new object();
		DoubleClickDetection doubleClickDetection;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructor
		/// </summary>
		public PropertyGridLabelControl()
		{
			base.DefaultStyleKey = typeof(PropertyGridLabelControl);
			this.doubleClickDetection = new DoubleClickDetection();
		}
		#endregion

		#region Properties

		/// <summary>
		/// Gets the PropertyGridEntry for this Label
		/// </summary>
		internal PropertyGridEntry PropertyEntry { get; set; }

		#region LabelText
		/// <summary>
		/// Gets or sets the Text to display for this label
		/// </summary>
		public string LabelText
		{
			get { return (string)GetValue(LabelTextProperty); }
			set { SetValue(LabelTextProperty, value); }
		}
		/// <summary>
		/// Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
		/// </summary>
		public static readonly DependencyProperty LabelTextProperty =
			DependencyProperty.Register("LabelText", typeof(string), typeof(PropertyGridLabelControl), new PropertyMetadata(string.Empty));
		#endregion

		#endregion

		#region Overrides
		/// <summary>
		/// Apply the control template.
		/// </summary>
		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();
			this.IsTabStop = false;
			this.UpdateVisualState(false, false, isReadOnly);
		}
		/// <summary>
		/// Process the KeyDown action.
		/// </summary>
		/// <param name="e">The KeyEventArgs args.</param>
		protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e)
		{
			Guard.ArgumentNotNull(e, "e");
			if (Keyboard.Modifiers == ModifierKeys.None)
			{
				switch (e.Key)
				{
					case System.Windows.Input.Key.Tab:
						e.Handled = true;
						this.OnToggleEditor();
						return;
				}
			}
			base.OnKeyDown(e);
		}
		/// <summary>
		/// Process the LostFocus action.
		/// </summary>
		/// <param name="e">The RoutedEventArgs args.</param>
		protected override void OnLostFocus(RoutedEventArgs e)
		{
			if (!this.PropertyEntry.IsEditorFocused)
			{
				this.PropertyEntry.IsActive = false;
				this.IsTabStop = false;
			}
			base.OnLostFocus(e);
		}
		/// <summary>
		/// Process the MouseLeftButtonUp action.
		/// </summary>
		/// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> args.</param>
		protected override void OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs e)
		{
			this.IsTabStop = true;
			if (this.doubleClickDetection.ProcessClick(key))
				this.OnDoubleClick(e);
			else
			{
				if (this.PropertyEntry.IsEditorFocused)
					this.PropertyEntry.Editor.EndEdit();
				else if (!this.PropertyEntry.IsActive)
					this.PropertyEntry.Activate();
			}
			base.OnMouseLeftButtonUp(e);
		}
		#endregion

		#region Methods
		internal void Initialize(PropertyGridEntry entry)
		{
			this.PropertyEntry = entry;
			this.isReadOnly = entry.Descriptor.IsReadOnly;
		}
		void OnToggleEditor()
		{
			this.PropertyEntry.Editor.ShouldSelectAllText = true;
			if (!this.PropertyEntry.Descriptor.IsReadOnly)
			{
				this.PropertyEntry.IsEditorFocused = true;
				this.PropertyEntry.Select();
			}
			else
				this.PropertyEntry.Editor.FocusDisplayControl();
		}
		internal void UpdateVisualState(bool selected, bool active, bool readOnly)
		{
			if (selected)
			{
				if (active)
				{
					if (readOnly)
						VisualStateManager.GoToState(this, STATE_SelectedActiveReadOnly, false);
					else
						VisualStateManager.GoToState(this, STATE_SelectedActive, false);
				}
				else
				{
					if (readOnly)
						VisualStateManager.GoToState(this, STATE_SelectedInactiveReadOnly, false);
					else
						VisualStateManager.GoToState(this, STATE_SelectedInactive, false);
				}
			}
			else
			{
				if (readOnly)
					VisualStateManager.GoToState(this, STATE_UnselectedReadOnly, false);
				else
					VisualStateManager.GoToState(this, STATE_Unselected, false);
			}
		}
		#endregion
	}
	#endregion
}
